package cn.wps.moffice.framework.thread;

import cn.wps.moffice.framework.util.KArrayUtil;

public class KThreadPool {

	static final boolean DEBUG = false; //DebugConfig.DEBUG;
	
	static final String  TAG = KThreadPool.class.getSimpleName();
	
	private static final int MAX_IDLE_THREAD = 5;
	
	static int sIdleThreadCount;
	static KThread[] sIdleThreads = new KThread[MAX_IDLE_THREAD];
	
	static int sThreadCount;
	static KThread[] sThreads = new KThread[KArrayUtil.idealIntArraySize(0)];
	
	static Object sLock = new Object();

	public static void threadExecute(Runnable runnable)
	{
		threadExecute(runnable, 0);
	}
	
	public static void threadExecute(Runnable runnable, long delayTime)
	{
		KThread thr = obtainThread();
		if (null != thr)
		{
			thr.autoJoinExecute(runnable, delayTime);
		}
	}
	
	private static KThread getIdleThreadLocked()
	{
		if (0 == sIdleThreadCount)
			return null;
		--sIdleThreadCount;
		KThread thread = sIdleThreads[sIdleThreadCount];
		sIdleThreads[sIdleThreadCount] = null;
		return thread;
	}
	
	private static int getThreadsEmptySlotLocked()
	{
		int index = -1;
		int length = sThreads.length;
		if (sThreadCount == length)
		{
			KThread[] threads = new KThread[KArrayUtil.idealIntArraySize(length)];
			System.arraycopy(sThreads, 0, threads, 0, length);
			sThreads = threads;
			index = length;
		}
		else
		{
			for (int i = 0; i < length; ++i)
			{
				if (null != sThreads[i])
					continue;
				index = i;
				break;
			}
		}
		return index;
	}
	
	public static KThread obtainThread()
	{
		synchronized (sLock) {
			KThread thread = getIdleThreadLocked();
			if (null != thread)
			{
				return thread;
			}
		}
		
		KThread thread = KThread.createThread();

		if (null == thread)
		{
			return null;
		}
		
		synchronized (sLock) {
			int index = getThreadsEmptySlotLocked();
			sThreads[index] = thread;
			++sThreadCount;
			thread._index = index;
		}

		return thread;
	}
	
	static void joinThreadPool(KThread thread)
	{
		if (thread._droped)
			return;
		synchronized (sLock) {
			if (thread._droped)
				return;
			if (sIdleThreadCount >= MAX_IDLE_THREAD)
			{
				sThreads[thread._index] = null;
				--sThreadCount;
				thread._droped = true;
				thread.quit();
			}
			else
			{
				sIdleThreads[sIdleThreadCount] = thread;
				++sIdleThreadCount;
			}
		}
	}

	public static void quit()
	{
		int length;
		KThread[] threads;
		synchronized (sLock) {
			length = sThreads.length;
			threads = new KThread[length];
			System.arraycopy(sThreads, 0, threads, 0, length);
			
			for (int i = 0; i < length; ++i)
			{
				KThread thread = sThreads[i];
				if (null != thread)
				{
					thread._droped = true;
					thread.quit();
				}
			}
			
			for (int i = 0; i < length; ++i)
			{
				sThreads[i] = null;
			}
			
			for (int i = 0; i < sIdleThreadCount; ++i)
			{
				sIdleThreads[i] = null;
			}
			
			sThreadCount = 0;
			sIdleThreadCount = 0;
		}

		for (int i = 0; i < length; ++i)
		{
			KThread thread = threads[i];
			if (null != thread && !thread.isQuited())
			{
				thread.waitQuit();
			}
		}
	}
}
